﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_COORDINATE_TRANSFORMATION_H
#define _UXS_COORDINATE_TRANSFORMATION_H

#pragma once

#include "MathTypesExt.h"

namespace UX_STL
{
namespace UXMathExt
{

	// Cartesian -> Spherical
	template <typename T>
	inline TVec<T,3>  CartesianToSpherical(const TVec<T,3> &vCartesian)
	{
		// x - radius
		// y - polar angle Theta
		// z - azimuthal angle Phi

		TVec<T,3>	spherical;

		spherical.x = vCartesian.Length();
		ASSERT( IsNotZero( spherical.x ) );

		spherical.y = ACos( vCartesian.z / spherical.x );
		spherical.z = ATan( vCartesian.y, spherical.x );

		return spherical;
	}


	// Spherical -> Cartesian
	template <typename T>
	inline TVec<T,3>  SphericalToCartesian(const TVec<T,3> &vSpherical)
	{
		// x - radius
		// y - polar angle Theta
		// z - azimuthal angle Phi

		TVec<T,3>		cartesian;
		TVec<T,2> const	theta = SinCos( vSpherical.y );
		TVec<T,2> const	phi   = SinCos( vSpherical.z );

		cartesian.x = vSpherical.x * theta.x * phi.y;
		cartesian.y = vSpherical.x * theta.x * phi.x;
		cartesian.z = vSpherical.x * theta.y;

		return cartesian;
	}


	// Spherical -> Cilindrical
	template <typename T>
	inline TVec<T,3>  SphericalToCilindrical(const TVec<T,3> &vSpherical)
	{
		// spherical:					cilindrical:
		// x - radius					x - radius
		// y - polar angle Theta		y - azimuthal angle Phi
		// z - azimuthal angle Phi		z - elevation

		TVec<T,3>		cilindrical;
		TVec<T,2> const	theta = SinCos( vSpherical.y );

		cilindrical.x = vSpherical.x * theta.x;
		cilindrical.y = vSpherical.z;
		cilindrical.z = vSpherical.x * theta.y;

		return cilindrical;
	}


	// Cilindrical -> Spherical
	template <typename T>
	inline TVec<T,3>  CilindricalToSpherical(const TVec<T,3> &vCilindrical)
	{
		// spherical:					cilindrical:
		// x - radius					x - radius
		// y - polar angle Theta		y - azimuthal angle Phi
		// z - azimuthal angle Phi		z - elevation

		TVec<T,3>		spherical;

		spherical.x = vCilindrical.xz().Length();
		spherical.y = ATan( vCilindrical.x, vCilindrical.y );
		spherical.z = vCilindrical.y;

		return spherical;
	}


	// Cartesian -> Cilindrical
	template <typename T>
	inline TVec<T,3>  CartesianToCilindrical(const TVec<T,3> &vCartesian)
	{
		// x - radius
		// y - azimuthal angle Phi
		// z - elevation

		TVec<T,3>	cilindrical;

		cilindrical.x = vCartesian.xy().Length();
		cilindrical.y = ATan( vCartesian.y / vCartesian.x );
		cilindrical.z = vCartesian.z;

		return cilindrical;
	}


	// Cilindrical -> Cartesian
	template <typename T>
	inline TVec<T,3>  CilindricalToCartesian(const TVec<T,3> &vCilindrical)
	{
		// x - radius
		// y - azimuthal angle Phi
		// z - elevation

		TVec<T,3>		cartesian;
		TVec<T,2> const	phi = SinCos( vCilindrical.y );

		cartesian.x = vCilindrical.x * phi.y;
		cartesian.y = vCilindrical.x * phi.x;
		cartesian.z = vCilindrical.z;

		return cartesian;
	}

	
//-------------------------------------------------------------------

}	// UXMathExt
}	// UX_STL

#endif	// _UXS_COORDINATE_TRANSFORMATION_H